/* Copyright 2009 Anthony Surma
This file is part of Java's Kademlia Extension (JKADX).

JKADX is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.

JKADX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JKADX.  If not, see <http://www.gnu.org/licenses/>.
 */

package jkadx.networking;

import java.io.IOException;
import java.net.SocketException;
import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

final class UDPSocketServer implements Runnable
{
    private final int incomingport;
    private final int length;
    private final SocketController socketcontroller;
    private DatagramSocket socket = null;

    private class ReceivedPackets implements Runnable
    {
	final private DatagramPacket packet;

	public ReceivedPackets(final DatagramPacket packet)
	{
	    this.packet = packet;
	}

	@Override
	public void run()
	{
            socketcontroller.received(packet); //pass packet to controller in a new thread
	}
    }
    
    UDPSocketServer(final SocketController controller,final int incomingport, final int length)
    {
	this.incomingport     = incomingport;
	this.length           = length;
	this.socketcontroller = controller;
    }

    // thread
    @Override
    public void run()
    {
	ExecutorService threadPool = Executors.newCachedThreadPool(); // XXX
	DatagramPacket packet = null;

	try
	{
	    // creates a socket to listen on incoming port
	    socket = new DatagramSocket(incomingport);
	}
	catch (SocketException e)
	{
	    System.out.println("Port chosen already in use.  Unable to open UDP socket.");
	    e.printStackTrace();
	}
	while (true)
	{
	    byte[] databuffer = new byte[length];
	    packet = new DatagramPacket(databuffer, databuffer.length);

	    try
	    {
                //System.out.println("Waiting for packet...");
		socket.receive(packet);        // waits for a packet
		threadPool.execute(new ReceivedPackets(packet)); // creates a thread to handle the packet
            } catch (SocketException e) // thrown when socket is closed
	    {                
		threadPool.shutdown();                
                return;
	    }
	    catch (IOException e) {}
	} 
    }

    //closes this socket
    void closeSocket() throws InterruptedException
    {        
        while (socket == null)
        {            
            Thread.sleep(4);
        }
        if (!socket.isClosed()) // if there's something to close
        {
	    socket.close();            	    
	}       
    }

    
    
}
